local cmp     = require("cmp")
local luasnip = require("luasnip")
local init    = require("init")

-- 加载 friendly-snippets
require("luasnip.loaders.from_vscode").lazy_load()

local check_backspace = function()
  local col = vim.fn.col(".") - 1
  return col == 0 or vim.fn.getline("."):sub(col, col):match("%s")
end

-- 设置补全图标
local kind_icons = {
  Text          = " 󰉿 ",
  Method        = " 󰆧 ",
  Function      = " 󰊕 ",
  Constructor   = "  ",
  Field         = " 󰜢 ",
  Variable      = " 󰀫 ",
  Class         = " 󰠱 ",
  Interface     = "  ",
  Module        = "  ",
  Property      = " 󰜢 ",
  Unit          = " 󰑭 ",
  Value         = " 󰎠 ",
  Enum          = "  ",
  Keyword       = " 󰌋 ",
  Snippet       = "  ",
  Color         = " 󰏘 ",
  File          = " 󰈙 ",
  Reference     = " 󰈇 ",
  Folder        = " 󰉋 ",
  EnumMember    = "  ",
  Constant      = " 󰏿 ",
  Struct        = " 󰙅 ",
  Event         = "  ",
  Operator      = " 󰆕 ",
  TypeParameter = "  ",
  Default       = "  ",
}

-- 设置补全项的颜色
local colors = {
  Keyword       = "#C586C0",
  Variable      = "#9CDCFE",
  Operator      = "#D4D4D4",
  Function      = "#DCDCAA",
  Method        = "#DCDCAA",
  Reference     = "#9CDCFE",
  Constant      = "#4FC1FF",
  Struct        = "#4EC9B0",
  Class         = "#4EC9B0",
  Interface     = "#4EC9B0",
  Text          = "#9CDCFE",
  Enum          = "#4EC9B0",
  EnumMember    = "#4FC1FF",
  Module        = "#C586C0",
  Color         = "#CE9178",
  Property      = "#9CDCFE",
  Field         = "#9CDCFE",
  File          = "#DCDCAA",
  Folder        = "#DCDCAA",
  Snippet       = "#C586C0",
  TypeParameter = "#4EC9B0",
  Constructor   = "#4EC9B0",
  Default       = "#D4D4D4",
  Event         = "#C586C0",
  Unit          = "#B5CEA8",
  Value         = "#9CDCFE",
}

-- 创建高亮组
for kind, color in pairs(colors) do
  vim.api.nvim_set_hl(0, "CmpItemKind" .. kind, { fg = "#1E1E1E", bg = color })
end
-- vim.api.nvim_set_hl(0, "CmpSel", { fg = "#181826", bg = "#7ec9d9", bold = true })
vim.api.nvim_set_hl(0, "CmpSel", { bg = "#45475a", bold = false })
vim.api.nvim_set_hl(0, "CmpItemAbbrMatch", { fg = "#15aabf", bold = true })
vim.api.nvim_set_hl(0, "CmpItemAbbr", { fg = "#cdd6f4" })

cmp.setup({
  snippet = {
    expand = function(args)
      luasnip.lsp_expand(args.body)
    end,
  },
  window = {
    completion = {
      scrollbar = true,
      winhighlight = "Normal:NormalFloat,FloatBorder:NormalFloat,CursorLine:CmpSel,Search:none",
      col_offset = -3,
      side_padding = 0,
    },
  },
  performance = {
    debounce = 0,                          -- 降低防抖时间，默认是60
    throttle = 10,                         -- 降低节流时间，默认是60
    fetching_timeout = 40,                 -- 设置获取补全项的超时时间
  },
  preselect = cmp.PreselectMode.Item,      -- 修改为默认选择第一个
  completion = {
    completeopt = 'menu,menuone,noinsert', -- 设置补全选项
  },
  formatting = {
    fields = { "kind", "abbr", "menu" },
    format = (function()
      return function(entry, vim_item)
        -- 设置图标和类型
        local kind = kind_icons[vim_item.kind] or kind_icons.Default
        vim_item.kind = kind
        -- vim_item.abbr = abbr
        -- vim_item.menu = menu
        return vim_item
      end
    end)(),
  },
  mapping = cmp.mapping.preset.insert({
    ["<C-k>"] = cmp.mapping(function()
      if luasnip.jumpable(-1) then
        luasnip.jump(-1)
      end
    end, { "i", "s" }),

    ["<C-j>"] = cmp.mapping(function()
      if luasnip.jumpable(1) then
        luasnip.jump(1)
      else
        local keys = vim.fn.Search_word()
        if keys ~= "\27" then -- 如果不是单纯的 ESC
          vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(keys, true, true, true), 'n', true)
        end
      end
    end, { "i", "s" }),
    ["<C-e>"] = cmp.mapping(cmp.mapping.scroll_docs(-1), { "i", "c" }),
    ["<C-f>"] = cmp.mapping(cmp.mapping.scroll_docs(1), { "i", "c" }),
    ["<C-o>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }),
    ["<CR>"] = cmp.mapping.confirm({ select = true }),
    ["<Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      elseif check_backspace() then
        fallback()
      else
        fallback()
      end
    end, {
      "i",
      "s",
    }),

    ["<S-Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_prev_item()
      else
        fallback()
      end
    end, {
      "i",
      "s",
    }),
  }),
  sources = {
    {
      name = "nvim_lsp",
      priority = 1000,
      max_item_count = 20,
      entry_filter = function(entry, ctx)
        -- 获取补全项的来源
        local source = entry.source
        if source and source.source and source.source.client then
          local client_name = source.source.client.name
          -- 如果是 emmet-ls 的补全，降低其优先级
          if client_name == "emmet_ls" then
            entry.score = entry.score * 0.1
          end
        end
        return true
      end
    },
    -- { name = "html-css", priority = 1000, max_item_count = 20},
    { name = "luasnip", priority = 750, max_item_count = 5 },
    { name = "buffer",  priority = 500, max_item_count = 10 },
    { name = "path",    priority = 250 },
  },
  sorting = {
    priority_weight = 2.0,              -- 设置优先级权重为 2.0，使不同来源的补全项的优先级差异更明显
    comparators = {
      cmp.config.compare.exact,         -- 完全匹配的项优先显示（例如：输入 'sta' 时，'start' 优先于 'restart'）
      cmp.config.compare.score,         -- 优先按照匹配度评分排序，这样最相关的补全项会排在前面
      cmp.config.compare.recently_used, -- 最近使用的项会排在相同类型的其他项前面（带有记忆性）
      cmp.config.compare.kind,          -- 按补全项的类型排序（变量、函数、关键字等）
      cmp.config.compare.locality,      -- 根据光标位置就近原则排序，较近的项优先显示
      cmp.config.compare.length,        -- 按补全项的长度排序（更短的项优先）
      cmp.config.compare.order,         -- 最后按照补全源的默认顺序排序
    },
  },
})
